package com.wfe.db;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.engine.Mangers.TaskRouter;
import com.wfe.mapping.client.WfAutofireplan;
import com.wfe.mapping.client.WfContextAttribute;
import com.wfe.mapping.client.WfFireActionDic;
import com.wfe.mapping.client.WfFirePlanAction;
import com.wfe.mapping.client.WfFirePlanActionCreator;
import com.wfe.mapping.client.WfPlan;
import com.wfe.mapping.client.WfPlanTask;
import com.wfe.mapping.client.WfProject;
import com.wfe.mapping.client.WfProjectStatus;
import com.wfe.mapping.client.WfProjectTask;
import com.wfe.mapping.client.WfProjectTaskStatus;
import com.wfe.mapping.client.WfTask;
import com.wfe.mapping.client.WfTaskRouting;
import com.wfe.mapping.client.WfTaskType;

/**
 * @author kareem_yehya
 * 
 */
public class WorkFlowEngineQueryUtil
{
	private static Random random = new Random();

	public static long getRandomID()
	{
		try
		{
			final int ran = random.nextInt(99999);
			final long date = System.currentTimeMillis();
			return Long.parseLong(date + "" + ran);
		}catch(final Exception e)
		{
			return System.currentTimeMillis();
		}
	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getWfProjectTask(Session session, long TaskID, int maxResults)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(TaskID > 0)
		{
			criteria.add(Restrictions.eq("recid", TaskID));
		}
		if(maxResults > 0)
		{
			criteria.setMaxResults(maxResults);
		}
		return criteria.list();
	}

	public static void updateWfProjectTask(WfProjectTask task, Session mySession)
	{
		mySession.update(task);
		mySession.beginTransaction().commit();

	}

	public static void updateContextAttribute(WfContextAttribute attribute, Session mySession)
	{
		mySession.update(attribute);
		mySession.beginTransaction().commit();

	}

	public static void addContextAttribute(WfContextAttribute attribute, Session session)
	{
		try
		{

			session.save(attribute);
			session.beginTransaction().commit();
		}catch(Exception e)
		{
			System.out.println(" you Tring to add an Attribute already in DB  Attributr Name = " + attribute.getAttributeName());
		}

	}

	public static WfProjectTaskStatus getWfProjectTaskStatusByID(long i, Session session)
	{
		Criteria criteria = session.createCriteria(WfProjectTaskStatus.class);
		criteria.add(Restrictions.eq("recid", i));
		return (WfProjectTaskStatus) criteria.list().get(0);
	}

	public static WfContextAttribute getContextAttributeByName(String attributeName, long TaskID, Session session)
	{
		try
		{
			Criteria criteria = session.createCriteria(WfProjectTask.class).add(Restrictions.eq("recid", TaskID));
			WfProjectTask wfProjTask = (WfProjectTask) criteria.uniqueResult();

			Set<WfContextAttribute> contextAttributesSet = wfProjTask.getWfProject().getWfFirePlanAction().getWfContextAttributes();

			for(WfContextAttribute wfContextAttribute : contextAttributesSet)
			{
				if(wfContextAttribute.getAttributeName().equals(attributeName))
				{
					return wfContextAttribute;
				}
			}
		}catch(Exception e)
		{
			System.out.println("Couldn't Retrive Attribute Name  = " + attributeName);
			return null;
		}
		return null;

	}

	// @SuppressWarnings("unchecked")
	// public static List<WfContextAttribute> getWfContextAttributeList(Session
	// session, int maxResults)
	// {
	// Criteria criteria = session.createCriteria(WfContextAttribute.class);
	//
	// if(maxResults > 0)
	// {
	// criteria.setMaxResults(maxResults);
	// }
	// return criteria.list();
	// }

	/**
	 * @author kareem_yehya
	 * @since 30 March 2009 <br>
	 *        This method for load unprocessed actions
	 * 
	 * 
	 * */

	@SuppressWarnings("unchecked")
	public static List<WfFirePlanAction> getWfFirePlanActionList(Session session, int maxResults)
	{
		try
		{
			Criteria criteria = session.createCriteria(WfFirePlanAction.class);
			criteria.add(Restrictions.eq("isProcessed", false));
			criteria.setMaxResults(maxResults);
			criteria.addOrder(Order.desc("priority"));
			return criteria.list();
		}catch(Exception e)
		{
			System.out.println("CAN NOT LOAD ACTIONS FROM DB");
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * @author kareem_yehya
	 * @since 02 April 2009 <br>
	 *        This method for load plans associated with this actions
	 * 
	 * 
	 * */

	// /////////////////////////////////////--------2 -------------
	@SuppressWarnings("unchecked")
	public static List<WfAutofireplan> getActionAutoFirePlans(Session session, WfFirePlanAction wfFirePlanAction)
	{
		try
		{
			Criteria criteria = session.createCriteria(WfAutofireplan.class);
			Criteria criteria1 = criteria.createCriteria("wfFireActionDic").add(Restrictions.eq("recid", wfFirePlanAction.getWfFireActionDic().getRecid()));
			return criteria1.list();

		}catch(Exception e)
		{
			System.out.print("CAN NOT LOAD Action Plan From DB");
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * @author kareem_yehya
	 * @since 02 April 2009 <br>
	 *        This method for load plan associated From AutoFirePlan
	 * 
	 * 
	 * */

	public static WfPlan getWfPlan(Session session, WfAutofireplan wfAutofireplan)
	{
		try
		{
			Criteria criteria = session.createCriteria(WfPlan.class);
			criteria.add(Restrictions.eq("recid", wfAutofireplan.getWfPlan().getRecid()));
			Criteria criteria1 = criteria.createCriteria("wfPlanStatus").add(Restrictions.eq("recid", 2L));
			return (WfPlan) criteria1.list().get(0);
		}catch(Exception e)
		{
			System.out.println("CAN NOT LOAD From WF_PLAN From DB");
			e.printStackTrace();
			return null;
		}

	}

	/**
	 * @author kareem_yehya
	 * @since 04 April 2009 <br>
	 *        Create New Project
	 * 
	 * 
	 * */

	public static void addWfProject(WfProject project, Session session)
	{
		try
		{
			session.save(project);
			session.beginTransaction().commit();
			System.out.println("project added ");
		}catch(Exception e)
		{
			System.out.println(" Couldn't Create new Project = " + project.getTitle());
		}

	}

	/**
	 * @author kareem_yehya
	 * @since 04 April 2009 <br>
	 *        Get A specific Project Status From DB
	 * 
	 * 
	 * */

	public static WfProjectStatus getwfProjectStatusByID(long i, Session session)
	{
		Criteria criteria = session.createCriteria(WfProjectStatus.class);
		criteria.add(Restrictions.eq("recid", i));
		return (WfProjectStatus) criteria.list().get(0);
	}

	/**
	 * @author kareem_yehya
	 * @since 04 April 2009 <br>
	 *        Get all plan tasks
	 * 
	 * 
	 * */

	@SuppressWarnings("unchecked")
	public static List<WfPlanTask> getPlanTasks(Session session, WfPlan wfPlan)
	{
		Criteria criteria = session.createCriteria(WfPlanTask.class);
		Criteria criteria1 = criteria.createCriteria("wfPlan").add(Restrictions.eq("recid", wfPlan.getRecid()));
		return criteria1.list();
	}

	/**
	 * @author kareem_yehya
	 * @since 04 April 2009 <br>
	 *        Add new Project Task
	 * 
	 * 
	 * */
	public static void addProjectTask(Session session, WfProjectTask projectTask)
	{
		session.save(projectTask);
		session.beginTransaction().commit();

	}

	/**
	 * @author kareem_yehya
	 * @since 04 April 2009 <br>
	 *        update action status to not executed again
	 * 
	 * 
	 * */

	public static void updateWfFirePlanAction(WfFirePlanAction action, Session mySession)
	{
		mySession.update(action);
		mySession.beginTransaction().commit();

	}

	// Reviewd
	public static void taskSucess(Session session, WfProjectTask projectTask)
	{
		WfProjectTask task = getWfProjectTaskByID(session, projectTask.getRecid());

		task.setWfProjectTaskStatus(getWfProjectTaskStatusByID(1l, session));
		task.setEndTime(new Date());
		updateWfProjectTask(task, session);
		Route(task, session);
		SessionUtil.closeSession(session);

	}

	// Reviewd
	public static void taskFailed(Session session, WfProjectTask projectTask)
	{
		WfProjectTask task = getWfProjectTaskByID(session, projectTask.getRecid());

		task.setWfProjectTaskStatus(getWfProjectTaskStatusByID(2l, session));
		task.setEndTime(new Date());
		updateWfProjectTask(task, session);
		Route(task, session);
		SessionUtil.closeSession(session);

	}

	public static void Route(WfProjectTask projectTask, Session session)
	{
		TaskRouter.route(projectTask, session);
	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getCreatedWfProjectTasks(Session session, long TaskID, int maxResults, WfTaskType taskType)
	{
		// WfTaskType taskType = getWfTaskTypeByID(2, session);
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(TaskID > 0)
		{
			criteria.add(Restrictions.eq("recid", TaskID));
		}
		if(maxResults > 0)
		{
			criteria.setMaxResults(maxResults);
		}
		// /************** created tasks
		criteria.add(Restrictions.eq("wfTaskType", taskType));
		Criteria criteria1 = criteria.createCriteria("wfProjectTaskStatus").add(Restrictions.eq("recid", 5l));

		return criteria1.list();
	}

	/**
	 * @author kareem_yehya
	 * @since 05 April 2009 <br>
	 *        get any task status
	 * 
	 * 
	 * */

	public static WfTaskType getWfTaskType(Session session, long tasktype)
	{
		Criteria criteria = session.createCriteria(WfTaskType.class);
		criteria.add(Restrictions.eq("recid", tasktype));
		return (WfTaskType) criteria.list().get(0);
	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getWfProjectTasksByStatus(Session session, long TaskID, int maxResults, WfTaskType taskType, long taskStatusID, boolean isProcessed)
	{
		// WfTaskType taskType = getWfTaskTypeByID(2, session);
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(TaskID > 0)
		{
			criteria.add(Restrictions.eq("recid", TaskID));
		}
		if(maxResults > 0)
		{
			criteria.setMaxResults(maxResults);
		}
		// /************** created tasks
		criteria.add(Restrictions.eq("wfTaskType", taskType));
		criteria.add(Restrictions.eq("isProcessed", isProcessed));
		Criteria criteria1 = criteria.createCriteria("wfProjectTaskStatus").add(Restrictions.eq("recid", taskStatusID));

		return criteria1.list();
	}

	/**
	 * @author kareem_yehya
	 * @since 16 04 2009 <br>
	 *        <H2>This Method Responsible retrive Project Tasks
	 * 
	 * 
	 * 
	 * */

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getProjectTasks(Session session, WfProjectStatus projectStatus, int maxResults, WfTaskType taskType, WfProjectTaskStatus wfProjectTaskStatus, boolean isProcessed)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(maxResults > 0)
		{
			criteria.setMaxResults(maxResults);
		}
		// /************** created tasks
		criteria.add(Restrictions.eq("wfTaskType", taskType));
		criteria.add(Restrictions.eq("isProcessed", isProcessed));
		criteria.add(Restrictions.eq("wfProjectTaskStatus", wfProjectTaskStatus));
		Criteria criteria1 = criteria.createCriteria("wfProject");
		criteria1.add(Restrictions.eq("wfProjectStatus", projectStatus));

		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getProjectTasks(Session session, WfProjectStatus projectStatus, int maxResults, WfTaskType taskType, WfProjectTaskStatus wfProjectTaskStatus, boolean isProcessed, WfTask wfTask)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(maxResults > 0)
		{
			criteria.setMaxResults(maxResults);
		}
		// /************** created tasks
		criteria.add(Restrictions.eq("wfTaskType", taskType));
		criteria.add(Restrictions.eq("isProcessed", isProcessed));
		criteria.add(Restrictions.eq("wfProjectTaskStatus", wfProjectTaskStatus));
		criteria.add(Restrictions.eq("wfTask", wfTask));

		Criteria criteria1 = criteria.createCriteria("wfProject");
		criteria1.add(Restrictions.eq("wfProjectStatus", projectStatus));

		return criteria.list();
	}

	public static void updateWfProject(WfProject project, Session session)
	{
		session.update(project);
		session.beginTransaction().commit();

	}

	public static WfProject getWfProjectByID(long recid, Session session)
	{
		Criteria criteria = session.createCriteria(WfProject.class);
		criteria.add(Restrictions.eq("recid", recid));
		return (WfProject) criteria.list().get(0);
	}

	public static WfProjectTask getWfProjectTaskByID(Session session, long TaskID)
	{

		Criteria criteria = session.createCriteria(WfProjectTask.class);
		criteria.add(Restrictions.eq("recid", TaskID));

		return (WfProjectTask) criteria.list().get(0);
	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getWfProjectTasksByProject(WfProject project, Session session)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class);
		criteria.add(Restrictions.eq("wfProject", project));
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public static List<WfTaskRouting> getWfTaskRoutingByWfPlanTask(Session session, WfPlanTask plantask)
	{
		Criteria criteria = session.createCriteria(WfTaskRouting.class);
		criteria.add(Restrictions.eq("wfPlanTask1", plantask));
		return criteria.list();

	}

	@SuppressWarnings("unchecked")
	public static List<WfTaskRouting> getPreviuosRoutingTasks(Session session, WfPlanTask plantask)
	{
		Criteria criteria = session.createCriteria(WfTaskRouting.class);
		criteria.add(Restrictions.eq("wfPlanTask2", plantask));
		return criteria.list();

	}

	/**
	 * @author kareem_yehya
	 * @since 16 April 2009 <br>
	 *        get any task status
	 * 
	 * 
	 * */

	public static WfTask getWfTask(Session session, long wfTaskID)
	{
		Criteria criteria = session.createCriteria(WfTask.class);
		criteria.add(Restrictions.eq("recid", wfTaskID));
		return (WfTask) criteria.list().get(0);
	}

	/**
	 * @author kareem_yehya
	 * @since 19 04 2009 <br>
	 *        Use this method to retrive any attributes using the task
	 * 
	 * 
	 * */

	public static List<WfContextAttribute> getAllAttributesByWfProjectTask(long taskID, Session session)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class).add(Restrictions.eq("recid", taskID));
		WfProjectTask wfProjTask = (WfProjectTask) criteria.uniqueResult();

		Set<WfContextAttribute> contextAttributesSet = wfProjTask.getWfProject().getWfFirePlanAction().getWfContextAttributes();
		if((contextAttributesSet != null) && (contextAttributesSet.size() > 0))
		{

			return new ArrayList<WfContextAttribute>(contextAttributesSet);
		}
		return null;
	}

	public static WfFirePlanActionCreator getActionCreator(Session session, long creatorID)
	{
		Criteria criteria = session.createCriteria(WfFirePlanActionCreator.class).add(Restrictions.eq("recid", creatorID));
		return (WfFirePlanActionCreator) criteria.list().get(0);
	}

	@SuppressWarnings("unchecked")
	public static WfFireActionDic getActionDic(Session session, long actionDicID)
	{
		try
		{
			Criteria criteria = session.createCriteria(WfFireActionDic.class).add(Restrictions.eq("recid", actionDicID));
			List<WfFireActionDic> dicList = criteria.list();
			if((dicList != null) && (dicList.size() > 0))
			{
				return dicList.get(0);
			}
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;

	}

	public static void addWfFirePlanAction(WfFirePlanAction wfFirePlanAction, Session session)
	{
		try
		{
			session.save(wfFirePlanAction);
			session.beginTransaction().commit();
		}catch(Exception e)
		{
			e.printStackTrace();
			System.out.println(" Couldn't Create new Action = ");
		}

	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> getWfProjectTaskIsProcessedNotHaveEndTime(Session session)
	{
		Date date = new Date();
		long oneHour = 1000 * 60 * 60;
		date.setTime(date.getTime() - oneHour);
		// System.out.println("date minus 1 hour = " + date);
		Criteria criteria = session.createCriteria(WfProjectTask.class);
		criteria.add(Restrictions.eq("isProcessed", true));
		criteria.add(Restrictions.isNull("endTime"));
		criteria.add(Restrictions.lt("startTime", date));
		criteria.createCriteria("wfProjectTaskStatus").add(Restrictions.eq("recid", 4L)); // assigned
		List<WfProjectTask> tasks = criteria.list();
		return tasks;
	}

	/**
	 * load tasks don't have route time and isrouted false
	 * 
	 * */
	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> loadTasksNeedRoute(Session session, WfProjectStatus projectStatus, int maxresults, WfTaskType taskType)
	{
		Criteria criteria = session.createCriteria(WfProjectTask.class);

		if(maxresults > 0)
		{
			criteria.setMaxResults(maxresults);
		}
		// /************** created tasks
		criteria.add(Restrictions.eq("wfTaskType", taskType));
		criteria.add(Restrictions.eq("isRouted", false));
		criteria.add(Restrictions.isNull("routeTime"));

		Criteria criteria1 = criteria.createCriteria("wfProject");
		criteria1.add(Restrictions.eq("wfProjectStatus", projectStatus));

		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public static List<WfProjectTask> loadStopedProcessTasks(Session session, WfProjectStatus projectStatus, int maxresults, WfTaskType taskType, WfProjectTaskStatus inprocessStatus)
	{
		Date date = new Date();
		long oneHour = 1000 * 60 * 60;
		date.setTime(date.getTime() - oneHour);
		Criteria criteria = session.createCriteria(WfProjectTask.class);
		if(maxresults > 0)
		{
			criteria.setMaxResults(maxresults);
		}
		criteria.add(Restrictions.isNull("endTime"));// no end time
		criteria.add(Restrictions.lt("startTime", date));// started from more
		// than one hour
		criteria.add(Restrictions.eq("isProcessed", false));// not executed
		criteria.add(Restrictions.eq("wfProjectTaskStatus", inprocessStatus));// inprocess
		criteria.add(Restrictions.eq("wfTaskType", taskType));// automatic
		Criteria criteria5 = criteria.createCriteria("wfProject");
		criteria5.add(Restrictions.eq("wfProjectStatus", projectStatus));

		List<WfProjectTask> tasks = criteria5.list();
		return tasks;
	}

	/**
	 * This Method use paging
	 * 
	 * */
	@SuppressWarnings("unchecked")
	public static List<WfProject> getInprocessProjectList(Session session, int maxResults, long taskID, int firstResult)
	{
		try
		{
			WfPlanTask currentPlanTask = (WfPlanTask) session.get(WfPlanTask.class, taskID);// TaskID
			long planID = currentPlanTask.getWfPlan().getRecid();

			WfProjectStatus wfProjectStatus = (WfProjectStatus) session.get(WfProjectStatus.class, 2L);// inprocess
			WfPlan currentPlan = (WfPlan) session.get(WfPlan.class, planID);// planID
			Criteria criteria = session.createCriteria(WfProject.class);
			criteria.setFirstResult(firstResult).setMaxResults(maxResults);
			criteria.add(Restrictions.eq("wfPlan", currentPlan));
			criteria.add(Restrictions.eq("wfProjectStatus", wfProjectStatus));
			return criteria.list();
		}catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}

	}

	public static WfPlanTask getWfPlanTaskbyID(Session session, long taskID)
	{
		Criteria criteria = session.createCriteria(WfPlanTask.class);
		criteria.add(Restrictions.eq("recid", taskID));
		criteria.setMaxResults(1);
		return (WfPlanTask) criteria.list().get(0);

	}
}
